import { debounce } from "@/utils/core.js";
/**
 鼠标移动到对象显示出来虚线
 */
const initManager = (
  canvas,
  minimap,
  $store,
  miniScale /*鹰眼按照比例进行缩小*/
) => {
  let ctx = canvas.getSelectionContext(),
    aligningLineWidth = 1,
    aligningLineColor = "rgb(0,0,0)",
    PS = [];

  //注册事件
  let KEYS = [
    {
      isKey(e) {
        return e.code == "KeyC" && e.ctrlKey;
      },
      action: "copy"
    },
    {
      isKey(e) {
        return e.code == "KeyV" && e.ctrlKey;
      },
      action: "paste"
    },
    {
      isKey(e) {
        return e.code == "Delete";
      },
      action: "del"
    },
    {
      isKey(e) {
        return e.code == "KeyG" && e.ctrlKey;
      },
      action: "group"
    },
    {
      isKey(e) {
        return e.code == "KeyU" && e.ctrlKey;
      },
      action: "ungroup"
    },
    {
      isKey(e) {
        return e.code == "KeyA" && e.ctrlKey;
      },
      action: "select"
    },
    {
      isKey(e) {
        return e.code == "Escape";
      },
      action: "unselect"
    },
    {
      isKey(e) {
        return e.code == "KeyZ" && e.ctrlKey;
      },
      action: "undo"
    },
    {
      isKey(e) {
        return e.code == "KeyY" && e.ctrlKey;
      },
      action: "redo"
    }
  ];

  //执行快捷键操作
  document.onkeydown = e => {
    //console.log(e);
    KEYS.map(o => {
      if (o.isKey(e)) {
        //执行命令
        $store.dispatch(o.action);

        e.preventDefault();
        e.stopPropagation();
      }
    });
  };

  //绘制
  let drawLine = points => {
    ctx.save();
    ctx.lineWidth = aligningLineWidth;
    ctx.strokeStyle = aligningLineColor;
    ctx.setLineDash([6, 6]);
    ctx.beginPath();

    ctx.moveTo(points[0].x, points[0].y);

    //把4个点连接起来
    ctx.lineTo(points[1].x, points[1].y);
    ctx.lineTo(points[2].x, points[2].y);
    ctx.lineTo(points[3].x, points[3].y);
    ctx.lineTo(points[0].x, points[0].y);

    ctx.stroke();
    ctx.restore();
  };

  //鼠标移动到对象的时候
  canvas.on("mouse:over", e => {
    if (e.target == null) return;
    //如果是当前选中的对象，就不要再显示
    if (e.target == canvas.getActiveObject()) return;

    //得到四个角的坐标
    let lineCoords = e.target.lineCoords;
    PS = [lineCoords.bl, lineCoords.br, lineCoords.tr, lineCoords.tl];

    canvas.renderAll();
  });

  canvas.on("before:render", () => {
    if (canvas.contextTop) {
      canvas.clearContext(canvas.contextTop);
    }
  });

  //清除线条
  canvas.on("after:render", () => {
    if (PS.length > 0) drawLine(PS);
  });

  let zoomAction = (e, flag) => {
    var delta = e.e.deltaY;
    var zoom = canvas.getZoom();

    //缩放到新的比例
    zoom *= 0.999 ** delta;
    if (zoom > 10) zoom = 10;
    if (zoom < 0.1) zoom = 0.1;

    //总是从中心点缩放...
    //let zoomPoint = new fabric.Point(canvas.width / 2, canvas.height / 2);

    //根据鼠标点进行放大缩小
    //减去偏移量，我操。。。。。
    let zoomPoint = new fabric.Point(
      //鼠标在屏幕的位置 - 对象的屏幕偏移量
      //   e.e.pageX -
      //   减去canvas便宜连
      //   canvas.wrapperEl.offsetLeft,
      //   e.e.pageY - canvas.wrapperEl.offsetTop

      //如果是绝对位置，是无法获取到offsetLeft内容
      e.e.pageX - ($store.state.app.leftState ? 376 : 72),
      e.e.pageY - 56
    );

    //如果是最小，按照中心缩放
    if (flag == "min") {
      zoomPoint = new fabric.Point(canvas.width / 2, canvas.height / 2);
    }

    //找到画布
    let bg = canvas.getObjects("_lxw_bg")[0];

    //计算画布的偏移的大小
    let x = 0;
    let y = 0;

    //按照坐标缩放
    canvas.zoomToPoint(zoomPoint, zoom);

    //得到画布相对canvas偏移量
    let bgRect = bg.getBoundingRect();
    //设置画布离canvas边的距离，小于这个就可以按照坐标放大
    let offset = 300;

    if (bgRect.width < canvas.width) {
      x = (canvas.width - bgRect.width) / 2;
    } else {
      //如果大于offset，就用offset作为距离canvas的大小。
      if (bgRect.left > offset) {
        x = offset;
      } else if (bgRect.left + bgRect.width < canvas.width - offset) {
        x = canvas.width - offset - bgRect.width;
      } else {
        //相当于不做任何改变
        x = canvas.viewportTransform[4] + bg.left * zoom;
      }
    }

    if (bgRect.height < canvas.height) {
      y = (canvas.height - bgRect.height) / 2;
    } else {
      //如果大于offset，就用offset作为距离canvas的大小。
      if (bgRect.top > offset) {
        y = offset;
      } else if (bgRect.top + bgRect.height < canvas.height - offset) {
        y = canvas.height - offset - bgRect.height;
      } else {
        //相当于不做任何改变
        y = canvas.viewportTransform[5] + bg.top * zoom;
      }
    }

    //重新定义位置，需要重新画布的偏移
    canvas.viewportTransform[4] = x - bg.left * zoom;
    canvas.viewportTransform[5] = y - bg.top * zoom;

    //更新选择区域对象的坐标
    canvas.forEachObject(o => {
      o.setCoords();
    });

    //去掉鼠标移动到对象上显示的点
    PS.length = 0;
    canvas.renderAll();

    //更新缩略图
    createMinimap(false);

    //阻止冒泡
    e.e.preventDefault();
    e.e.stopPropagation();
  };

  //放大缩小进行画面位置操作
  //应该所有的事件放到一个里面
  canvas.on("mouse:wheel", e => {
    zoomAction(e, "max");
  });
  minimap.on("mouse:wheel", e => {
    //已选择区域中心点放大
    zoomAction(e, "min");
  });

  //鼠标移开
  canvas.on("mouse:out", e => {
    //不要显示对象四周的虚线
    PS.length = 0;
    canvas.renderAll();
  });

  let __panning = false;
  canvas.on("mouse:down", e => {
    if (e.e.altKey) {
      console.log("mouse:down");
      __panning = true;
      canvas.selection = false;

      canvas
        .getObjects()
        .filter(o => !o.lxwname)
        .map(o => {
          o.selectable = false;
        });
    }

    PS.length = 0;
    canvas.renderAll();
  });

  canvas.on("mouse:up", e => {
    // console.log(
    //   "mouse:up",
    //   e,
    //   canvas.getActiveObject(),
    //   canvas.getActiveObject().type
    // );
    if (__panning && e && e.e) {
      createMinimap(false);
    }

    __panning = false;
    canvas.selection = true;

    canvas
      .getObjects()
      .filter(o => !o.lxwname)
      .map(o => {
        o.selectable = true;
      });

    let select = canvas.getActiveObject();
    if (select != null) console.log(select.type);
    $store.dispatch("setSelectedObj", select);
  });

  //拖动画布
  canvas.on("mouse:move", e => {
    if (__panning && e && e.e) {
      console.log("mouse:move");
      var delta = new fabric.Point(e.e.movementX, e.e.movementY);
      canvas.relativePan(delta);
    }
  });

  //   canvas.on("mouse:dblclick", e => {
  //     //console.log("mouse:dblclick", e);
  //   });

  //var debouncedMiniMap = debounce(updateMiniMap, 250);

  canvas.on("object:modified", function() {
    //updateMiniMap();
    createMinimap(false);
  });

  //监视对象移动事件
  minimap.on("object:moving", e => {
    //监视对象的位置，反向移动画布区域
    let rectView = minimap._objects[0];
    let bg = canvas.getObjects("_lxw_bg")[0];

    //缩放比例
    let bl = bg.width / (minimap.width / miniScale);

    //寻找缩略图中心点在画布的位置对应到大画布的中心点位置
    let centerX =
      canvas.width / 2 -
      (rectView.left - ((minimap.width / miniScale) * (miniScale - 1)) / 2) *
        bl *
        canvas.getZoom();
    canvas.viewportTransform[4] = centerX - bg.left * canvas.getZoom();

    let centerY =
      canvas.height / 2 -
      (rectView.top - ((minimap.height / miniScale) * (miniScale - 1)) / 2) *
        bl *
        canvas.getZoom();
    canvas.viewportTransform[5] = centerY - bg.top * canvas.getZoom();

    //更新选择区域对象的坐标
    canvas.forEachObject(o => {
      o.setCoords();
    });

    canvas.renderAll();
  });

  let refrashView = () => {
    //生成小图片
    let bg = canvas.getObjects("_lxw_bg")[0];
    //缩放比例
    let bl = bg.width / (minimap.width / miniScale);
    //重新定位可视化区域大小和位置...
    //放大缩小 拖动 都需调用这个
    let rect = {
      left: 0,
      top: 0,
      width: canvas.width / canvas.getZoom() / bl,
      height: canvas.height / canvas.getZoom() / bl
    };

    //得到画布的偏离位置
    let bgRect = bg.getBoundingRect();

    //得到可视化区域大小
    let rectView = minimap._objects[0];

    rectView.left =
      (canvas.width / 2 - bgRect.left) / canvas.getZoom() / bl +
      ((minimap.width / miniScale) * (miniScale - 1)) / 2;

    rectView.top =
      (canvas.height / 2 - bgRect.top) / canvas.getZoom() / bl +
      ((minimap.height / miniScale) * (miniScale - 1)) / 2;

    rectView.width = rect.width;
    rectView.height = rect.height;

    //重新更新拖动的区域
    rectView.setCoords();
  };

  //加载完毕生成小图
  let createMinimap = first => {
    //生成小图片
    let bg = canvas.getObjects("_lxw_bg")[0];
    //缩放比例
    let bl = bg.width / (minimap.width / miniScale);

    //生成一个大图
    let tempCanvas = new fabric.StaticCanvas();
    tempCanvas.setWidth(bg.width);
    tempCanvas.setHeight(bg.height);

    console.log("canvas.toJSON()", canvas.toJSON(), canvas.toSVG());

    //生成一个大图
    tempCanvas.loadFromJSON(canvas.toJSON(), () => {
      console.log("加载成功!!", bl);
      tempCanvas.backgroundColor = "white";
      //平移视图
      tempCanvas.viewportTransform = [1, 0, 0, 1, -bg.left, -bg.top];
      tempCanvas.renderAll();

      //缩小到这个比例
      var canvas = tempCanvas.toCanvasElement(1 / bl);

      tempCanvas = null;

      //背景加载到中间
      if (first) {
        //第一次创建，第二次就直接变化背景
        var backgroundImage = new fabric.Image(canvas);
        minimap.centerObject(backgroundImage);
        minimap.backgroundColor = "rgba(0,0,0,0.5)";
        minimap.backgroundImage = backgroundImage;

        //半透明状态
        var minimapView = new fabric.Rect({
          top: backgroundImage.top,
          left: backgroundImage.left,
          width: backgroundImage.width,
          height: backgroundImage.height,
          fill: "rgba(0, 255, 255, 0.2)",
          cornerSize: 6,
          originX: "center",
          originY: "center",
          transparentCorners: true,
          cornerColor: "blue",
          stroke: "blue",
          hasBorders: false,
          strokeWidth: 1
        });
        //不要显示可控制的点
        minimapView.controls = {
          //br: fabric.Object.prototype.controls.br
        };
        minimap.add(minimapView);
      } else {
        minimap.backgroundImage._element = canvas;
      }

      refrashView();
      minimap.requestRenderAll();
    });
  };

  createMinimap(true);

  //创建蒙版和出血线
  let createMask = () => {
    //全选的时候不要选中这些对象
    //得到背景对象
    let bg = canvas.getObjects("_lxw_bg")[0];
    let bgRect = bg.getBoundingRect();

    //弄几个超大的背景覆盖。
    canvas.remove(...canvas.getObjects("_lxw_mask"));
    //canvas.remove(...canvas.getObjects("sBg"));
    const pathOption = {
      selectable: false,
      fill: "rgba(220,220,220,1)",
      hoverCursor: "default",
      evented: false,
      excludeFromExport: true,
      hasControls: false,
      perPixelTargetFind: false,
      strokeWidth: 0,
      //   originX: "center",
      //   originY: "center",
      stroke: null
    };

    let chuxie = (3 * 96) / 25.4;
    let jiaoxian = (6 * 96) / 25.4;

    const maxPadding = 40000;
    const top = new fabric.Rect({
      width: maxPadding,
      height: maxPadding / 2
    });
    const left = new fabric.Rect({
      width: maxPadding / 2,
      height: bg.height
    });
    const right = new fabric.Rect({
      width: maxPadding / 2 - bg.width,
      height: bg.height
    });
    const bottom = new fabric.Rect({
      width: maxPadding,
      height: maxPadding / 2
    });

    const center = new fabric.Rect({
      width: bg.width - chuxie * 2,
      height: bg.height - chuxie * 2
    });

    top.set({
      left: 0,
      top: 0,
      name: "mask1",
      ...pathOption
    });
    left.set({
      left: 0,
      top: maxPadding / 2,
      name: "mask2",
      ...pathOption
    });
    right.set({
      left: maxPadding / 2 + bg.width,
      top: maxPadding / 2,
      name: "mask3",
      ...pathOption
    });
    bottom.set({
      left: 0,
      top: maxPadding / 2 + bg.height,
      name: "mask4",
      ...pathOption
    });
    center.set({
      left: maxPadding / 2 + chuxie,
      top: maxPadding / 2 + chuxie,
      name: "mask5",
      selectable: false,
      fill: "rgba(0,0,0,0)",
      hoverCursor: "default",
      evented: false,
      excludeFromExport: true,
      hasBorders: true,
      perPixelTargetFind: false,
      strokeWidth: 1,
      stroke: "#000",
      //绘制虚线
      strokeDashArray: [6, 6]
      //   originX: "center",
      //   originY: "center",
      //stroke: null
    });

    let linesArr = [
      [
        maxPadding / 2 - jiaoxian,
        maxPadding / 2 + chuxie,
        maxPadding / 2,
        maxPadding / 2 + chuxie
      ],
      [
        maxPadding / 2 + chuxie,
        maxPadding / 2 - jiaoxian,
        maxPadding / 2 + chuxie,
        maxPadding / 2
      ],

      [
        maxPadding / 2 - jiaoxian,
        maxPadding / 2 - chuxie + bg.height,
        maxPadding / 2,
        maxPadding / 2 - chuxie + bg.height
      ],
      [
        maxPadding / 2 + chuxie,
        maxPadding / 2 + jiaoxian + bg.height,
        maxPadding / 2 + chuxie,
        maxPadding / 2 + bg.height
      ],

      [
        maxPadding / 2 + bg.width,
        maxPadding / 2 + chuxie,
        maxPadding / 2 + bg.width + jiaoxian,
        maxPadding / 2 + chuxie
      ],
      [
        maxPadding / 2 + bg.width - chuxie,
        maxPadding / 2 - jiaoxian,
        maxPadding / 2 + bg.width - chuxie,
        maxPadding / 2
      ],
      [
        maxPadding / 2 + bg.width,
        maxPadding / 2 - chuxie + bg.height,
        maxPadding / 2 + bg.width + jiaoxian,
        maxPadding / 2 - chuxie + bg.height
      ],
      [
        maxPadding / 2 + bg.width - chuxie,
        maxPadding / 2 + jiaoxian + bg.height,
        maxPadding / 2 + bg.width - chuxie,
        maxPadding / 2 + bg.height
      ]
    ];
    var lines = [];
    linesArr.map(o => {
      let f = new fabric.Line(o);
      f.set({
        selectable: false,
        fill: "rgba(0,0,0,0)",
        hoverCursor: "default",
        evented: false,
        excludeFromExport: true,
        hasBorders: true,
        perPixelTargetFind: false,
        strokeWidth: 1,
        stroke: "#000"
      });
      lines.push(f);
    });

    //画8跟线条在里面
    //在里面再画一矩形

    //, left, right, bottom
    let maskPath = new fabric.Group(
      [top, left, right, bottom, center, ...lines],
      {
        selectable: false,
        excludeFromExport: true,
        lockMovementX: true,
        lockMovementY: true,
        lockRotation: true,
        lockScalingX: true,
        lockScalingY: true,
        lockUniScaling: true,
        hoverCursor: "auto",
        opacity: 0.8,
        name: "mask",
        left: bgRect.left / canvas.getZoom() - top.width / 2,
        top: bgRect.top / canvas.getZoom() - top.height,
        type: "_lxw_mask",
        //自定义名称
        lxwname: "_lxw_",
        evented: false
      }
    );

    // const cir = new fabric.Circle({
    //   left: 100,
    //   top: 100,
    //   radius: 30,
    //   fill: "rgba(0, 0, 0, 0)"
    // });

    // cir.setGradient("fill", {
    //   x1: 0,
    //   y1: 0,
    //   x2: 0,
    //   y2: 0,
    //   type: "radial",
    //   r1: 30,
    //   r2: 2,
    //   colorStops: {
    //     0: "red",
    //     0.2: "orange",
    //     0.4: "yellow",
    //     0.6: "green",
    //     0.8: "blue",
    //     1: "purple"
    //   }
    // });
    // canvas.add(cir);

    canvas.add(maskPath);
    canvas.bringToFront(maskPath);
    canvas.renderAll();

    // // 创建中间画布的背景
    // state.backgroundPanel = new fabric.Rect({
    //   left: arrX[0],
    //   top: arrY[0],
    //   selectable: false,
    //   evented: false,
    //   width: state.pannelW,
    //   height: state.pannelH,
    //   strokeWidth: 0,
    //   fill: !state.activePage ? "#ffffff" : "rgba(0, 0, 0, 0)",
    //   objectCaching: false,
    //   hoverCursor: "default",
    //   excludeFromExport: true,
    //   hasControls: false,
    //   type: "sBg",
    //   perPixelTargetFind: false
    // });
  };

  //创建蒙版
  createMask();
};

//初始化界面
export default initManager;
